package com.hh.erp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hh.erp.entity.*;
import com.hh.erp.entity.request.SysUserRequest;
import com.hh.erp.entity.vo.*;
import com.hh.erp.mapper.*;
import com.hh.erp.service.SysDictDataService;
import com.hh.erp.service.SysUserService;
import com.hh.erp.util.DateTimeUtil;
import com.hh.erp.util.JsonUtil;
import com.hh.erp.util.RedisUtil;
import com.hh.erp.util.StringUtil;
import com.hh.erp.util.http.*;
import com.hh.erp.util.page.PageInfo;
import com.mysql.cj.log.Log;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.ref.ReferenceQueue;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author zhb
 * @since 2024-03-30
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private SysPostMapper sysPostMapper;
    @Autowired
    private SysUserPostMapper sysUserPostMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    // Services
    @Autowired
    private SysDictDataService sysDictDataService;


    @Override
    public String login(String username, String password) {
        if(StringUtil.IsSpace(username)) {
            throw new DiscoveryException("用户名不能为空!");
        }
        if(StringUtil.IsSpace(password)) {
            throw new DiscoveryException("密码不能为空!");
        }
        SysUser user = this.baseMapper.login(username,password);
        if(user == null) {
            throw new DiscoveryException("用户或密码错误!");
        }
        if(StringUtil.Equals(user.getStatus(),"1")) {
            throw new DiscoveryException("该账号已停用!");
        }

        String token = StringUtil.getToken();
        UserInfoVo userInfoVo = new UserInfoVo();
        // 角色集合
        List<SysRole> roles = sysRoleMapper.getRolePermission(user);
        List<SysMenu> menus = new ArrayList<>();
        // 权限集合
        if(user.isAdmin()) {
            menus = sysMenuMapper.selectList(new
                    QueryWrapper<SysMenu>()
                    .eq(SysMenu.STATUS,0)
                    .in(SysMenu.MENU_TYPE, new String[]{"M", "C"})
            );
        }
        else {
            menus = sysMenuMapper.getMenuPermission(user);
        }

        List<SysMenuVo> menuVos = new ArrayList<>();
        menus.stream().forEach(p->{
            SysMenuVo vo = new SysMenuVo();
            BeanUtils.copyProperties(p,vo);
            menuVos.add(vo);
        });

        userInfoVo.setUser(user);
        userInfoVo.setRoles(roles);
        userInfoVo.setMenus(menuVos);
        RedisUtil.add(token, JsonUtil.toJson(userInfoVo));
        return token;
    }

//    @Override
//    public AjaxResult getInfo(String token) {
//        String jsonStr = RedisUtil.getValue(token);
//        UserInfoVo userInfoVo = JsonUtil.toObject(RedisUtil.getValue(token),UserInfoVo.class);
//        // 用户信息
//        SysUser user = userInfoVo.getUser();
//        // 角色集合
//        Set<String> roles = userInfoVo.getRoles().stream().map(p->p.getRoleKey()).distinct().collect(Collectors.toSet());
//        // 权限集合
//        Set<String> permissions = new HashSet<>();
//        if(user.isAdmin()){
//            permissions.add("*:*:*");
//
//        }
//        else {
//            permissions = userInfoVo.getMenus().stream().map(p->p.getPerms()).distinct().collect(Collectors.toSet());
//        }
//        AjaxResult result = AjaxResult.success();
//        result.put("user", user);
//        result.put("roles", roles);
//        result.put("permissions", permissions);
//        return result;
//    }

    /**
     * 重写，固定三级架构
     * MenuType  M  目录  如系统管理、系统监控，系统工具等
     * MenuType  C  菜单
     * MenuType  F  按钮
     *
     * @param token
     * @return
     */
    @Override
    public List<RouterVo> getRouters(String token) {
        String jsonStr = RedisUtil.getValue(token);
        UserInfoVo userInfoVo = JsonUtil.toObject(RedisUtil.getValue(token), UserInfoVo.class);
        // 目录+ 菜单集合
        List<SysMenuVo> menus = RouterUtil.restRouter(userInfoVo.getMenus(), 0L);
        //System.out.println("menus:"+JsonUtil.toJson(menus));
        // 路由信息
        List<RouterVo> routers = new LinkedList<RouterVo>();
        for (SysMenuVo menu : menus) {
            RouterVo router = new RouterVo();
            router.setHidden("1".equals(menu.getVisible()));
            router.setName(RouterUtil.getRouteName(menu));
            router.setPath(RouterUtil.getRouterPath(menu));
            router.setComponent(RouterUtil.getComponent(menu));
            router.setQuery(menu.getQuery());
            router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtil.Equals("1", menu.getIsCache()), menu.getPath()));
            List<SysMenuVo> cMenus = menu.getChildren();
            if (!StringUtil.IsSpace(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(RouterUtil.buildMenus(cMenus));
            } else if (RouterUtil.isMenuFrame(menu)) {
                router.setMeta(null);
                List<RouterVo> childrenList = new ArrayList<RouterVo>();
                RouterVo children = new RouterVo();
                children.setPath(menu.getPath());
                children.setComponent(menu.getComponent());
                children.setName(StringUtil.capitalize(menu.getPath()));
                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtil.Equals("1", menu.getIsCache()), menu.getPath()));
                children.setQuery(menu.getQuery());
                childrenList.add(children);
                router.setChildren(childrenList);
            } else if (menu.getParentId().intValue() == 0 && RouterUtil.isInnerLink(menu)) {
                router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
                router.setPath("/");
                List<RouterVo> childrenList = new ArrayList<RouterVo>();
                RouterVo children = new RouterVo();
                String routerPath = RouterUtil.innerLinkReplaceEach(menu.getPath());
                children.setPath(routerPath);
                children.setComponent(UserConstants.INNER_LINK);
                children.setName(StringUtil.capitalize(routerPath));
                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
                childrenList.add(children);
                router.setChildren(childrenList);
            }
            routers.add(router);
        }
        return routers;
    }

    @Override
    public PageInfo selectPageUserList(SysUserRequest request) {
        PageInfo page = LoginUtil.getPageInfo();
        List<SysUserVo> data = this.baseMapper.selectUserList(page,request);

        // 部门信息
        List<SysDept> depts = sysDeptMapper.selectDeptList();
        Map<Long,SysDept> deptMap = depts.stream().collect(Collectors.toMap(p->p.getDeptId(),p->p));

        // data 数据处理
        data.stream().forEach(p->{
            if(p.getDeptId() != null && deptMap.containsKey(p.getDeptId())) {
                p.setDept(deptMap.get(p.getDeptId()));
            }
        });

        Long total = this.baseMapper.selectUserListCount(page,request);
        page.setPageData(data,total);
        return page;
    }

    @Override
    public SysUser findUserById(Long id) {
        SysUser user = this.baseMapper.selectById(id);
        user.setPassword(Constants.INIT_PASSWORD);
        return user;
    }

    public List<String> saveCheck(SysUserRequest request) {

        List<String> msgList = new ArrayList<>();

        if(request == null) {
            msgList.add("请求数据为空！");
        }

        // 修改用户检查
        if(request.getUserId() != null && request.getUserId() > 0L) {
            SysUser user = this.baseMapper.selectById(request.getUserId());
            if(user == null) {
                msgList.add("修改的用户不存在！");
            }
            if (user != null) {
                if (!StringUtil.Equals(request.getUserName(), user.getUserName())) {
                    Integer count = this.baseMapper.selectCount(
                            new QueryWrapper<SysUser>()
                                    .eq(SysUser.USER_NAME, request.getUserName())
                                    .ne(SysUser.USER_ID, user.getUserId())
                    );
                    if (count > 0) {
                        msgList.add("修改的用户名已存在！");
                    }
                }
            }
        }
        //新增用户检查
        else  {
            if(StringUtil.IsSpace(request.getUserName())) {
                msgList.add("用户名不能为空！");
            }
            if(StringUtil.IsSpace(request.getPassword())) {
                msgList.add("密码不能为空！");
            }
        }
        return msgList;
    }

    @Transactional
    @Override
    public Boolean edit(SysUserRequest request) {
        List<String> msgList = this.saveCheck(request);
        if( msgList.size() > 0 ) {
            throw new DiscoveryException("用户检查失败："+ msgList.stream().collect(Collectors.joining("\n")));
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(request,sysUser);
        sysUser.setUpdateBy(LoginUtil.getUserInfo().getUser().getUserName());
        sysUser.setUpdateTime(LocalDateTime.now());
        Integer rowCount = this.baseMapper.updateById(sysUser);
        if(rowCount < 1) {
            throw new DiscoveryException("修改用户档案失败！");
        }

        //岗位
        sysUserPostMapper.deleteByUserId(sysUser.getUserId());
        List<Long> postIds = request.getPostIds();
        if(postIds != null && postIds.size() > 0) {
            postIds.stream().distinct().forEach(p->{
                SysPost sysPost = sysPostMapper.selectById(p);
                if(sysPost == null) {
                    throw new DiscoveryException("岗位ID: "+p +" 数据不存在");
                }
                SysUserPost data = new SysUserPost();
                data.setUserId(sysUser.getUserId());
                data.setPostId(sysPost.getPostId());
                sysUserPostMapper.insert(data);
            });
        }
        //角色
        sysUserRoleMapper.deleteByUserId(sysUser.getUserId());
        List<Long> roleIds = request.getRoleIds();
        if(roleIds != null && roleIds.size() > 0) {
            roleIds.stream().distinct().forEach(p->{
                SysRole sysRole = sysRoleMapper.selectById(p);
                if(sysRole == null) {
                    throw new DiscoveryException("角色ID: "+p +" 数据不存在");
                }
                SysUserRole data = new SysUserRole();
                data.setUserId(sysUser.getUserId());
                data.setRoleId(sysRole.getRoleId());
                sysUserRoleMapper.insert(data);
            });
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean add(SysUserRequest request) {
        List<String> msgList = this.saveCheck(request);
        if( msgList.size() > 0 ) {
            throw new DiscoveryException("用户检查失败："+ msgList.stream().collect(Collectors.joining("\n")));
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(request,sysUser);
        sysUser.setCreateBy(LoginUtil.getUserInfo().getUser().getUserName());
        sysUser.setCreateTime(LocalDateTime.now());
        sysUser.setUpdateBy(sysUser.getCreateBy());
        sysUser.setUpdateTime(sysUser.getCreateTime());
        Integer rowCount = this.baseMapper.insert(sysUser);
        if(rowCount < 1) {
            throw new DiscoveryException("新增用户档案失败！");
        }

        //岗位
        List<Long> postIds = request.getPostIds();
        if(postIds != null && postIds.size() > 0) {
            postIds.stream().distinct().forEach(p->{
                SysPost sysPost = sysPostMapper.selectById(p);
                if(sysPost == null) {
                    throw new DiscoveryException("岗位ID: "+p +" 数据不存在");
                }
                SysUserPost data = new SysUserPost();
                data.setUserId(sysUser.getUserId());
                data.setPostId(sysPost.getPostId());
                sysUserPostMapper.insert(data);
            });
        }
        //角色
        List<Long> roleIds = request.getRoleIds();
        if(roleIds != null && roleIds.size() > 0) {
            roleIds.stream().distinct().forEach(p->{
                SysRole sysRole = sysRoleMapper.selectById(p);
                if(sysRole == null) {
                    throw new DiscoveryException("角色ID: "+p +" 数据不存在");
                }
                SysUserRole data = new SysUserRole();
                data.setUserId(sysUser.getUserId());
                data.setRoleId(sysRole.getRoleId());
                sysUserRoleMapper.insert(data);
            });
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean changeStatus(SysUserRequest request) {
        if(request.getUserId() == null) {
            throw new DiscoveryException("用户ID:"+ request.getUserId()+ "数据不存在");
        }
        if(StringUtil.IsSpace(request.getStatus())) {
            throw new DiscoveryException("没有指定要修改的用户状态！");
        }
        String SysStatus = "sys_notice_status";
        // 检查要更新的状态是否在范围内
        List<SysDictData> dictList = sysDictDataService.getDictDatas(SysStatus);
        if(dictList == null || dictList == null) {
            throw new DiscoveryException("数据状态字典："+SysStatus + "未找到状态数据");
        }
        if(dictList.stream().filter(p->StringUtil.Equals(p.getDictValue(),request.getStatus())).count() != 1) {
            throw new DiscoveryException("指定更新的状态不在数据字典内！");
        }
        SysUser user = this.baseMapper.selectById(request.getUserId());
        if(user == null) {
            throw new DiscoveryException("用户ID:"+ request.getUserId()+ "数据不存在");
        }
        SysUser newUser = new SysUser();
        newUser.setUserId(user.getUserId());
        newUser.setStatus(request.getStatus());
        newUser.setUpdateBy(LoginUtil.getUserInfo().getUser().getUserName());
        newUser.setUpdateTime(LocalDateTime.now());
        Integer count = this.baseMapper.updateById(newUser);
        if(count != 1) {
            throw new DiscoveryException("用户状态数据更新失败！");
        }
        return true;
    }

    /**
     * 不需要从数据库直接删除数据，因为有很多表会用到ID带出名称。
     * @param userId
     * @return
     */
    @Transactional
    @Override
    public Boolean deleteById(Long userId) {
        if(userId == null) {
            throw new DiscoveryException("用户ID:"+ userId+ "数据不存在");
        }

        SysUser user = this.baseMapper.selectById(userId);
        if(user == null) {
            throw new DiscoveryException("用户ID:"+ userId+ "数据不存在");
        }

        SysUser newUser = new SysUser();
        newUser.setUserId(user.getUserId());
        newUser.setDelFlag("Y");
        newUser.setUpdateBy(LoginUtil.getUserInfo().getUser().getUserName());
        newUser.setUpdateTime(LocalDateTime.now());
        Integer count = this.baseMapper.updateById(newUser);
        if(count != 1) {
            throw new DiscoveryException("用户删除失败！");
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean resetPwd(SysUserRequest request) {
        if(request.getUserId() == null) {
            throw new DiscoveryException("用户ID:"+ request.getUserId()+ "数据不存在");
        }
        if(StringUtil.IsSpace(request.getPassword())) {
            throw new DiscoveryException("修改后的用户密码不能为空！");
        }
        SysUser user = this.baseMapper.selectById(request.getUserId());
        if(user == null) {
            throw new DiscoveryException("用户ID:"+ request.getUserId()+ "数据不存在");
        }
        SysUser newUser = new SysUser();
        newUser.setUserId(user.getUserId());
        newUser.setPassword(request.getPassword());
        newUser.setUpdateBy(LoginUtil.getUserInfo().getUser().getUserName());
        newUser.setUpdateTime(LocalDateTime.now());
        Integer count = this.baseMapper.updateById(newUser);
        if(count != 1) {
            throw new DiscoveryException("用户密码数据更新失败！");
        }
        return true;
    }
}
